﻿using System;
using System.IO;
using System.Text;
using System.Web;
using System.Web.Mvc;
using Mvc4Demo.Core;

namespace Mvc4Demo.Controllers
{
    public abstract class BaseController : Controller
    {
        protected ActionResult ViewPdf(object model)
        {
            //get html data
            var htmlData = RenderActionResultToString(View(model));

            var memoryStream = PdfConverter.HtmlToPdf(htmlData);
            memoryStream.Position = 0;
            return new FileStreamResult(memoryStream, "application/pdf");

            //If file FileStreamResult doesn't work then comment out above two lines and uncomment below code 
            //var buffer = new byte[memoryStream.Position];
            //memoryStream.Position = 0;
            //memoryStream.Read(buffer, 0, buffer.Length);
            // Send the binary data to the browser.
            //return new FileContentResult(buffer, "application/pdf");

            //return new BinaryContentResult(buffer, "application/pdf");
        }


        /// <summary>
        ///render action result as string.
        /// </summary>
        /// <param name="result"></param>
        /// <returns></returns>
        protected string RenderActionResultToString(ActionResult result)
        {
            // Create memory writer.
            var sb = new StringBuilder();
            var memWriter = new StringWriter(sb);

            // Create fake http context to render the view.
            var fakeResponse = new HttpResponse(memWriter);
            var fakeContext = new HttpContext(System.Web.HttpContext.Current.Request, fakeResponse);
            var fakeControllerContext = new ControllerContext(
                new HttpContextWrapper(fakeContext),
                ControllerContext.RouteData,
                ControllerContext.Controller);

            var oldContext = System.Web.HttpContext.Current;
            System.Web.HttpContext.Current = fakeContext;

            // Render the view.
            result.ExecuteResult(fakeControllerContext);

            // Restore old context.
            System.Web.HttpContext.Current = oldContext;

            // Flush memory and return output.
            memWriter.Flush();
            return sb.ToString();
        }

        protected override void OnException(ExceptionContext filterContext)
        {
            var lastError = filterContext.Exception;
            if (lastError == null)
                return;
            var messages = new StringBuilder();
            //find actual exception
            var actulaException = GetInternalException(lastError, messages);
            //get the last exception message
            var errorMessage = actulaException.Message;
            filterContext.HttpContext.Response.StatusCode = 500;
            if (Request.IsAjaxRequest())
            {
                filterContext.Result = Json(new
                {
                    Message = errorMessage
                });
                filterContext.ExceptionHandled = true;
                return;
            }

            ViewBag.Message = errorMessage;
            filterContext.Result = View("Error");
        }

        private static Exception GetInternalException(Exception exception, StringBuilder messages)
        {
            messages.AppendFormat("{0}:{1}", exception.GetType(), exception.Message);
            if (exception.InnerException != null)
                messages.Append('\n');

            return exception.InnerException == null
                       ? exception
                       : GetInternalException(exception.InnerException, messages);
        }


    }
}